<?php

namespace W3;

/**
 * 配置管理类
 *
 * @author edikud
 * @date 2022/10/22
 * @copyright Copyright (c) 2022 W3 (http://www.mcooo.com)
 * @license GNU General Public License 2.0
 */
class Config
{
    /**
     * 单例句柄
     *
     * @access protected
     * @var Config
     */
    protected static $instance;
	
    /**
     * 单例实例
     *
     * @return Config
     */
    public static function instance(): Config
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * 创建新的配置存储库
     *
     * @access public
     * @return Config
     */
    public static function make($arguments = ''): Config
    {
        return new static($arguments);
    }
	
    /**
     * 实例化一个当前配置  
     *
     * @access public
     * @param mixed $config 配置列表
     */
    public function __construct($arguments = '')
    {
        $this->default($arguments);
    }

    /**
     * 设置给定的配置值
     *
     * @param  array|string  $key
     * @param  mixed  $value
     * @return void
     */
    public function set($key, $value = null)
    {
        $keys = is_array($key) ? $key : [$key => $value];

        foreach ($keys as $key => $value) 
		{
            $this->{$key} =  $value;
        }
    }
	
    /**
     * 设置默认参数
     *
     * @param  string|array  $arguments  参数
     * @return void
     */
    public function default($arguments = []) 
    {
        if (empty($arguments)) {
            return;
        }

        /** 初始化参数 */
        if (is_string($arguments)) {
            parse_str($arguments, $params);
        } else {
            $params = $arguments;
        }

		$merged = $this->export();
		$merged = empty($merged) ? $params : Util::arrayDiffMerge($merged, $params);

        foreach ($merged as $property => $argument) 
		{
			$this->{$property} =  $argument;
        }
    }
	
    /**
     * 合并参数
     *
     * @param  string|array  $arguments  参数
     * @return void
     */
    public function merge($arguments = []) 
    {
        if (empty($arguments)) {
            return;
        }

        /** 初始化参数 */
        if (is_string($arguments)) {
            parse_str($arguments, $params);
        } else {
            $params = $arguments;
        }
		$merged = $this->export();
		$merged = empty($merged) ? $params : Util::arrayMerge($merged, $params);

        foreach ($merged as $property => $argument) 
		{
			$this->{$property} =  $argument;
        }
    }

    /**
     * 输出所有配置项
     *
     * @return array
     */
    public function export(): array
    {
		$items = [];
        foreach ($this as $name => $value) 
		{
            $items[$name] = $value;
        }
		
        return $items;
    }
	
    /**
     * 数组开头添加配置值
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return void
     */
    public function prepend($key, $value)
    {
        $array = $this->get($key);

        array_unshift($array, $value);

        $this->set($key, $array);
    }

    /**
     * 数组末尾添加配置值
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return void
     */
    public function push($key, $value)
    {
        $array = $this->get($key);

        $array[] = $value;

        $this->set($key, $array);
    }
	
    /**
     * 根据选项的名称检索选项值
     *
     * @param string $name  要检索的选项的名称
     * @param mixed  $default Optional. 如果该选项不存在，则返回默认值。
     * @return mixed 为选项设置的值
     */
    public function get(string $name, $default = false)
    {
        return $this->{$name} ?? $default;
    }

    /**
     * 返回堆栈中选项的名称筛选的检索列表
     *
     * @param string|[] $list 
     * @return []
     */
    public function many(...$list): array
    {
		$list = is_array($list[0]) ? $list[0] : $list;
		
		$items = [];
        foreach ($list as $name) 
		{
            $items[$name] = $this->{$name};
        }
		
        return $items;
    }

    /**
     * 判断当前配置值是否存在
     *
     * @access public
     * @param string $name 配置名称
     * @return boolean
     */
    public function has(string $name): bool
    {
		return isset($this->$name);
    }

    /**
     * 魔术函数设置一个配置值
     *
     * @access public
     * @param string $name 配置名称
     * @param mixed $value 配置值
     * @return void
     */
    public function __set(string $name, $value = null)
    {
        $this->{$name} = $value;
    }
	
    /**
     * 判断当前配置值是否存在
     *
     * @access public
     * @param string $name 配置名称
     * @return boolean
     */
    public function __isset(string $name): bool
    {
        return isset($this->$name);
    }

    /**
     * Support unset() overloading on PHP 5.1
     *
     * @param  string $name
     * @throws Exception
     * @return void
     */
    public function __unset(string $name)
    {
        unset($this->$name);
    }
	
	/**
	 * 创建一次 对象
	 * @param string $var 
	 * @return object
	 */
	public function __get(string $name) 
	{
		return $this->$name = NULL;
	}
	
    /**
     * 魔术函数,用于挂接其它函数
     *
     * @access public
     * @param string $name 函数名
     * @param array $args 函数参数
     * @return void
     */
    public function __call(string $name, array $args)
    {
		echo $this->{$name};
    }
}
